package com.shujia

object Demo12Func2 {
  /**
    * 函数式编程（高阶函数）
    * 面向对象编程 把对象传来传去 对象作为参数传入时会有类型限制 对象作为返回值是也会有限制
    * 面向函数编程 把函数传来传去 函数作为参数传入时会有类型限制 函数作为返回值是也会有限制
    *
    * 分为两类：
    * 1、以函数作为参数
    * 2、以函数作为返回值
    *
    *
    * 什么是函数的类型？
    * 跟def关键字无关
    * 跟函数名是无关的
    * 跟函数实现的功能无关
    * 跟函数的参数名无关
    *
    * 函数的类型是由 参数的类型（类型、个数、顺序）以及返回值类型共同决定
    */
  // func1是一个（有一个参数，参数类型为String，返回值类型为Int）类型的函数
  def func1(str1: String): Int = {
    str1.toInt + 1
  }

  // func2是一个（有一个参数，参数类型为String，返回值类型为Int）类型的函数
  def func2(str2: String): Int = {
    str2.toInt + 2
  }

  // func3是一个（有一个参数，参数类型为Int，返回值类型为Int）类型的函数
  // func1和func2属于同类型的函数 func3不属于
  def func3(i: Int): Int = {
    i + 3
  }

  /**
    * f: String => Int
    * f: 是funcX函数所需要的参数的参数名
    * String => Int 是funcX函数所需要的参数的类型（比较特殊，这里描述的是一个函数类型）
    * => 左边的部分 表示 所传进来的函数 它的参数类型
    * => 右边的部分 表示 所传进来的函数 它的返回值类型
    */

  // 定义了一个函数 它可以接收一个函数
  def funcX(f: String=> Int)={
    val i: Int = f("200")
    println(i)
  }


  /**
    * lambda 表达式 匿名函数
    * 简化函数
    *
    */
  // 定义一个lambda表达式
  // 定义了一个有两个参数 类型分别为String、Int
  // 返回值为Int这样一个匿名函数
  (str:String,i:Int) =>{
    str.toInt+i
  }

  // 用lambda表达式简化func1的定义
  // 虽然是匿名函数 但也可以拥有名字
 val i: String => Int = (str:String) => str.toInt+1


  def main(args: Array[String]): Unit = {
    funcX(func1)
    funcX(func2)

    // 使用lambda表达式
    funcX((str:String) => {str.toInt+1})
    // lambda的简化
    // 1、如果代码只有一行 花括号可以省略
    // 2、参数的类型可以省略 括号也可以顺便省略
    // 3、如果参数只被调用了一次 则可以使用_下划线代替
    funcX((str:String) => str.toInt+1)
    funcX(str => str.toInt+1)
    funcX(_.toInt+1)
    funcX(i)
    println(i("100"))
  }
}
